package sjsu.cmpe235;

import java.io.IOException;
import java.util.List;
import java.util.regex.Pattern;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.google.zxing.WriterException;
import com.google.zxing.client.android.integration.IntentIntegrator;
import com.google.zxing.client.android.integration.IntentResult;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.encoder.ByteMatrix;

import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.drawable.Drawable;
import android.telephony.SmsManager;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends MapActivity {	
	
	private MapView map=null;
	private LocationManager locationManager;

	// Define Regular expressions to use to identify the type of barcode from the scanned code
	private Pattern imagePattern = Pattern.compile("([^\\s]+(\\.(?i)(jpg|png|gif|bmp))$)");
	private Pattern mediaPattern = Pattern.compile("([^\\s]+(\\.(?i)(3gp|mp4|m4a|aac|mp3|ogg|wav|webm|mkv))$)");
	private Pattern websitePattern =  Pattern.compile("(http|https)://.*");

	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        Log.d("BARCODE","Activity Started: initialize the controls");
        
        // Splash Screen
        startActivity(new Intent(this, SplashActivity.class));              
        
        // Find reference to UI components by ID
        Button buttonScan = (Button) findViewById(R.id.buttonScan);
        Button buttonURL = (Button) findViewById(R.id.buttonURL);
	    Button buttonSMS = (Button) findViewById(R.id.buttonSMS);
	    EditText editPhone = (EditText) findViewById(R.id.editPhone);
	    TextView txtPhone = (TextView) findViewById(R.id.txtPhone);
	    
	    // Assign on-click event handler for buttons
	    ClickHandler onclick = new ClickHandler();
	    
        buttonScan.setOnClickListener(onclick);        
	    buttonURL.setOnClickListener(onclick);	    
	    buttonSMS.setOnClickListener(onclick);
	    
	    // Hide buttons (because we don't have result to process these actions)
	    buttonURL.setVisibility(View.GONE);
        buttonSMS.setVisibility(View.GONE);
        txtPhone.setVisibility(View.GONE);
        editPhone.setVisibility(View.GONE);
        
        // ------------- Optional ------------------
        // MapView control for Bonus
        map=(MapView)findViewById(R.id.map);

        // Get current location from LocationManager
        // get Best provider (if GPS sensor is not available, use approximate location)
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        String provider = locationManager.getBestProvider(new Criteria(), true);	
        Location location = locationManager.getLastKnownLocation(provider);
        
        // if location is returned
        if (location != null) {   
            // Initialize the map view and display
    		map.getController().setCenter(getPoint(location.getLatitude(),location.getLongitude()));
    		map.getController().setZoom(17);
    		map.setBuiltInZoomControls(true);	    		    		   
        } else {
        	// Display error message and hide the map
        	Toast.makeText(getBaseContext(), "Location Not Available",Toast.LENGTH_SHORT).show();
        	map.setVisibility(View.GONE);
        }
    }

    // inner class for button click event handler
    private class ClickHandler implements OnClickListener{
    	public void onClick(View view) {
	    	
    		//Intent intent = new Intent("com.google.zxing.client.android.SCAN");      
	    	
    		switch(view.getId()){
		        case R.id.buttonScan:
		        	Log.d("BARCODE","Scan Button Clicked");
		        	
		        	// Start QRcode scanner
					IntentIntegrator.initiateScan(MainActivity.this);
					
		        break;
		        case R.id.buttonURL:		        
		        	Log.d("BARCODE","Open URL Button Clicked");

		        	String scannedURL = ((TextView)findViewById(R.id.txtResult)).getText().toString();
		        	
		        	// Open web site for returned URL (this will open default web browser with URL)		        	
		        	 Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(scannedURL));
		        	 startActivity(i);
		        break;
		        case R.id.buttonSMS:
		        	String phonenumber = ((EditText)findViewById(R.id.editPhone)).getText().toString();
		        	String message = ((TextView)findViewById(R.id.txtResult)).getText().toString();
		        	
		        	if (phonenumber.length() == 0)
		        	{
		        		alert("Phone number is missing. Please enter it and try again");
		        	}
		        	else
		        	{
			        	// Send SMS with returned URL
		        		sendSMS(phonenumber,message);	        	
		        	}

		        break;
		    }
	    }   	
    }// end of inner class
    
    //sends an SMS message
    private void sendSMS(String phoneNumber, String message)
    {        
        PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, new Intent("SMS_SENT"), 0);

        //---after the SMS has been sent---
        registerReceiver(new BroadcastReceiver(){
            @Override
            public void onReceive(Context arg0, Intent arg1) {
                switch (getResultCode())
                {
                    case Activity.RESULT_OK:
                        Toast.makeText(getBaseContext(), "SMS successfully sent",Toast.LENGTH_SHORT).show();
                        break;
                    case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                        Toast.makeText(getBaseContext(), "Generic failure",Toast.LENGTH_SHORT).show();
                        break;
                    case SmsManager.RESULT_ERROR_NO_SERVICE:
                        Toast.makeText(getBaseContext(), "No service",Toast.LENGTH_SHORT).show();
                        break;
                    case SmsManager.RESULT_ERROR_NULL_PDU:
                        Toast.makeText(getBaseContext(), "Null PDU",Toast.LENGTH_SHORT).show();
                        break;
                    case SmsManager.RESULT_ERROR_RADIO_OFF:
                        Toast.makeText(getBaseContext(), "Radio off",Toast.LENGTH_SHORT).show();
                        break;
                }
            }
        }, new IntentFilter("SMS_SENT"));

        // initialize the SMS Manager and send out the message
        SmsManager sms = SmsManager.getDefault();
        sms.sendTextMessage(phoneNumber, null, message, sentPI, null);        
    }
    
    // build custom alert dialog box
	public void alert(String message){    		
		AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
 
		// set title
		alertDialogBuilder.setTitle("Missing Phone Number");
 
		// set dialog message
		alertDialogBuilder
				.setMessage(message)
				.setCancelable(false)
				.setPositiveButton("OK",new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog,int id) {
						// if this button is clicked, just close
						// the dialog box and do nothing
						dialog.cancel();
					}
				});
				
 		// create alert dialog
		AlertDialog alertDialog = alertDialogBuilder.create();
 
		// show it
		alertDialog.show();
	}
    
	void displayBarcode(String code) {
        QRCodeWriter writer = new QRCodeWriter();
        ByteMatrix matrix = null;
        try {
            matrix = writer.encode(code, BarcodeFormat.QR_CODE, 256, 256);
        } catch (WriterException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }    
        if (matrix != null) {            
            try {
                //File file = new File("test.png");
                MatrixToImageWriter.writeToFile(matrix, "PNG", file);
                //System.out.println(file.getAbsolutePath());                
            }
            catch (IOException e) {
                System.out.println(e.getMessage());                
            }
        }        
    }
	
    // Run this after scanning is done
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    	
    	// Debugging messages
    	Log.d("BARCODE","Scanner returned result");
    	Log.d("BARCODE","Request Code:" + requestCode);
    	Log.d("BARCODE","Result Code:" + resultCode);
    	
    	// if scan was successful
	    if (requestCode != 0) {
	    	// Decode the scanned result
	    	IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
			        
	    	// find the reference to controls by ID
			TextView txtStartScan=(TextView)findViewById(R.id.txtStartScan);
			TextView txtResult=(TextView)findViewById(R.id.txtResult);
			Button buttonURL = (Button) findViewById(R.id.buttonURL);
			Button buttonSMS = (Button) findViewById(R.id.buttonSMS);
			EditText editPhone = (EditText) findViewById(R.id.editPhone);
			TextView txtPhone = (TextView) findViewById(R.id.txtPhone);
	      
	      if (resultCode == RESULT_OK) {
	    	// return the decoded barcode as string
	    	String code = result.getContents();
	        txtResult.setText(code);
	        
	        // TODO: 
	        // 1) when scan was successful, generate the barcode and display it in the imageview along with the result.
	        displayBarcode(code);
	        // 2) make a request to server using json API
	        // 		2-1) call performAction() to execute the required action.
	        
	        
	        

	        buttonURL.setVisibility(View.GONE);
	        buttonSMS.setVisibility(View.VISIBLE);
	        txtPhone.setVisibility(View.VISIBLE);
	        editPhone.setVisibility(View.VISIBLE);

	        
	    	// parse the code and trigger the correct intent
	    	performAction(code);
	        
	      } else if (resultCode == RESULT_CANCELED) {
	    	
	    	// Notify user that scanning has been canceled
	        txtResult.setText("Scan cancelled.");
	        
	        // Hide buttons (because there is no result)
	        buttonURL.setVisibility(View.GONE);
	        buttonSMS.setVisibility(View.GONE);
	        txtPhone.setVisibility(View.GONE);
	        editPhone.setVisibility(View.GONE);
	      }	      
	    }
    }
	
    private void performAction(String code) {

    	if ( mediaPattern.matcher(code).matches() )
    	{
            Toast.makeText(getBaseContext(), "Multimedia Content Detected",Toast.LENGTH_SHORT).show();

    		// if it is media (audio or video) start media player
	    	Intent i = new Intent(this, MediaPlayerActivity.class);
	        i.putExtra("mediaURL", code);
	    	startActivity(i);
    	}else if (imagePattern.matcher(code).matches()){
            Toast.makeText(getBaseContext(), "Image Detected",Toast.LENGTH_SHORT).show();

            // start ImageViewer activity 
	    	Intent i = new Intent(this, WebActivity.class);
	        i.putExtra("webURL", code);
	    	startActivity(i);
    	}else if ( websitePattern.matcher(code).matches()) {
    		Toast.makeText(getBaseContext(), "Website Detected",Toast.LENGTH_SHORT).show();

            // start ImageViewer activity 
	    	Intent i = new Intent(this, WebActivity.class);
	        i.putExtra("webURL", code);
	    	startActivity(i);
    	}
    	// TODO: else if ( coordinate )
    	// TODO: else if ( contact/bizcard )
    }

	private GeoPoint getPoint(double lat, double lon) {
		return(new GeoPoint((int)(lat*1000000.0),(int)(lon*1000000.0)));
	}
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        
        // TODO: personal profile or settings here.
        
        return true;
    }

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}
}
